package com.jdd.modules.area.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jdd.common.constant.CacheConstant;
import com.jdd.common.constant.JddConstant;
import com.jdd.common.util.MathUtil;
import com.jdd.common.util.SnowFlakeUtil;
import com.jdd.modules.area.entity.ChargeRulesModule;
import com.jdd.modules.area.entity.ChargeRulesModuleStep;
import com.jdd.modules.area.mapper.ChargeRulesModuleMapper;
import com.jdd.modules.area.service.IChargeRulesModuleService;
import com.jdd.modules.area.service.IChargeRulesModuleStepService;
import com.jdd.modules.area.vo.ChargeRulesModuleVO;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description: 停车场计费规则模块表
 * @Author: jdd
 * @Date: 2021-07-13
 * @Version: V1.0
 */
@Service
public class ChargeRulesModuleServiceImpl extends ServiceImpl<ChargeRulesModuleMapper, ChargeRulesModule> implements IChargeRulesModuleService {

    @Resource
    ChargeRulesModuleMapper chargeRulesModuleMapper;
    @Resource
    private IChargeRulesModuleStepService chargeRulesModuleStepService;

    /**
     * 得到计费规则
     *
     * @param chargeRuleId 计费规则id
     * @return 计费规则模块
     * @date 2021-08-10 16:36
     * @author: liuyaowen
     */
    @Override
    public List<ChargeRulesModule> getChargeRulesModule(String chargeRuleId) {
        LambdaQueryWrapper<ChargeRulesModule> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ChargeRulesModule::getChargeRulesId, chargeRuleId);
        queryWrapper.orderBy(true, true, ChargeRulesModule::getStartTimeHour, ChargeRulesModule::getStartTimeMinute);
        List<ChargeRulesModule> list = this.list(queryWrapper);
        if (CollectionUtil.isEmpty(list)) {
            return null;
        } else {
            return list;
        }
    }

    @Override
    public ChargeRulesModule getNextChargeRuleModule(ChargeRulesModule chargeRulesModule) {
        LambdaQueryWrapper<ChargeRulesModule> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ChargeRulesModule::getChargeRulesId, chargeRulesModule.getChargeRulesId());
        queryWrapper.orderBy(true, true, ChargeRulesModule::getStartTimeHour, ChargeRulesModule::getStartTimeMinute);
        List<ChargeRulesModule> list = this.list(queryWrapper);
        List<ChargeRulesModule> nextChargeRuleModules = new ArrayList<>();
        // 如果数据库中无区间计费规则
        if (CollectionUtil.isEmpty(list)) {
            return null;
        }
        // 如果数据库中只存在一条计费规则
        if (list.size() == 1) {
            return list.get(0);
        } else {
            // 如果数据库中存在多条计费规则，获取所有的开始时间在被编辑的计费规则的开始时间之后的计费规则
            nextChargeRuleModules = list.stream().filter(module -> (!module.getId().equals(chargeRulesModule.getId())) && (module.getStartTimeHour() > chargeRulesModule.getStartTimeHour()) || (module.getStartTimeHour().equals(chargeRulesModule.getStartTimeHour()) && module.getStartTimeMinute() > chargeRulesModule.getStartTimeMinute())).collect(Collectors.toList());
            // 如果不存在开始时间在被编辑的计费规则的开始时间之后的计费规则
            if (CollectionUtil.isEmpty(nextChargeRuleModules)) {
                // 返回所有的计费规则中的第一条数据
                return list.get(0);
            } else {
                // 如果存在，返回开始时间在被编辑的计费规则的开始时间之后的第一条计费规则
                return nextChargeRuleModules.get(0);
            }
        }
    }

    @Override
    public ChargeRulesModule getPrimaryChargeRuleModule(ChargeRulesModule chargeRulesModule) {

        LambdaQueryWrapper<ChargeRulesModule> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ChargeRulesModule::getChargeRulesId, chargeRulesModule.getChargeRulesId());
        queryWrapper.orderBy(true, false, ChargeRulesModule::getStartTimeHour, ChargeRulesModule::getStartTimeMinute);
        List<ChargeRulesModule> list = this.list(queryWrapper);
        List<ChargeRulesModule> primaryChargeRuleModules = new ArrayList<>();
        // 如果数据库中无区间计费规则
        if (CollectionUtil.isEmpty(list)) {
            return null;
        }
        if (list.size() == 1) {
            return list.get(0);
        } else {
            // 如果数据库中存在多条计费规则，获取所有的开始时间在被编辑的计费规则的开始时间之后的计费规则
            primaryChargeRuleModules = list.stream().filter(module -> (!module.getId().equals(chargeRulesModule.getId())) && (module.getStartTimeHour() < chargeRulesModule.getStartTimeHour()) || (module.getStartTimeHour().equals(chargeRulesModule.getStartTimeHour()) && module.getStartTimeMinute() < chargeRulesModule.getStartTimeMinute())).collect(Collectors.toList());
            // 如果不存在开始时间在被编辑的计费规则的开始时间之后的计费规则
            if (CollectionUtil.isEmpty(primaryChargeRuleModules)) {
                // 返回所有的计费规则中的第一条数据
                return list.get(0);
            } else {
                // 如果存在，返回开始时间在被编辑的计费规则的开始时间之后的第一条计费规则
                return primaryChargeRuleModules.get(0);
            }
        }
    }

    /**
     * 清空所有绑定指定计费规则Id的计费规则模块
     *
     * @param chargeRuleId
     * @return
     */
    @Override
    public Boolean removeByChargeRulesId(String chargeRuleId) {
        LambdaQueryWrapper<ChargeRulesModule> deleteQueryWrapper = new LambdaQueryWrapper<>();
        deleteQueryWrapper.eq(ChargeRulesModule::getChargeRulesId, chargeRuleId);
        return this.remove(deleteQueryWrapper);
    }

    @Override
    public boolean updateById(ChargeRulesModule chargeRulesModule) {
        return super.updateById(chargeRulesModule);
    }

    @Override
    public boolean save(ChargeRulesModule chargeRulesModule) {
        return super.save(chargeRulesModule);
    }

    @Override
    public boolean removeById(Serializable id) {
        return super.removeById(id);
    }

    /**
     * 清空表数据
     *
     * @return true 清空成功
     */
    @Override
    public boolean removeAllInfo() {
        try {
            chargeRulesModuleMapper.removeAllInfo();
        } catch (Exception e) {
            return false;
        }
        return true;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String add(ChargeRulesModuleVO chargeRulesModuleVO) throws Exception {
        String result = "";
        ChargeRulesModule chargeRulesModule = chargeRulesModuleVO.getChargeRulesModule();

        chargeRulesModule.setId(SnowFlakeUtil.getId());

        LambdaQueryWrapper<ChargeRulesModule> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ChargeRulesModule::getChargeRulesId, chargeRulesModule.getChargeRulesId());
        queryWrapper.eq(ChargeRulesModule::getStartTimeHour, chargeRulesModule.getStartTimeHour());
        queryWrapper.eq(ChargeRulesModule::getStartTimeMinute, chargeRulesModule.getStartTimeMinute());
        if (CollectionUtil.isNotEmpty(this.list(queryWrapper))) {
            throw new Exception("重复配置");
        }
        ChargeRulesModule primaryChargeRuleModule = this.getPrimaryChargeRuleModule(chargeRulesModule);
        ChargeRulesModule nextChargeRuleModule = this.getNextChargeRuleModule(chargeRulesModule);
        if (nextChargeRuleModule == null) {
            chargeRulesModule.setEndTimeHour(chargeRulesModule.getStartTimeHour());
            chargeRulesModule.setEndTimeMinute(chargeRulesModule.getStartTimeMinute());
        } else {
            primaryChargeRuleModule.setEndTimeHour(chargeRulesModule.getStartTimeHour());
            primaryChargeRuleModule.setEndTimeMinute(chargeRulesModule.getStartTimeMinute());
            chargeRulesModule.setEndTimeHour(nextChargeRuleModule.getStartTimeHour());
            chargeRulesModule.setEndTimeMinute(nextChargeRuleModule.getStartTimeMinute());
            if (JddConstant.ChargeConstant.CHARGE_RULE_MODULE_CHARGE_TYPE_STEP.equals(primaryChargeRuleModule.getChargeType())) {
                result = "此计费时段的前置时段被修改，请及时调整";
            }
            this.updateById(primaryChargeRuleModule);
        }
        this.save(chargeRulesModule);
        if (JddConstant.ChargeConstant.CHARGE_RULE_MODULE_CHARGE_TYPE_STEP.equals(chargeRulesModule.getChargeType())) {
            List<ChargeRulesModuleStep> addArray = new ArrayList<>();
            List<ChargeRulesModuleStep> stepArray = chargeRulesModuleVO.getStepArray();
            for (ChargeRulesModuleStep chargeRulesModuleStep : stepArray) {
                chargeRulesModuleStep.setChargeRulesModuleId(chargeRulesModule.getId());
                chargeRulesModuleStep.setId(SnowFlakeUtil.getId());
                addArray.add(chargeRulesModuleStep);
            }
            chargeRulesModuleStepService.saveBatch(addArray);
        }
        return "添加成功！" + result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String edit(ChargeRulesModuleVO chargeRulesModuleVO) throws Exception {
        String result = "";
        ChargeRulesModule chargeRulesModule = chargeRulesModuleVO.getChargeRulesModule();
        ChargeRulesModule chargeRulesModuleEntity = this.getById(chargeRulesModule.getId());
        if (chargeRulesModuleEntity == null) {
            throw new Exception("未找到对应实体");
        } else {
            LambdaQueryWrapper<ChargeRulesModule> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.ne(ChargeRulesModule::getId, chargeRulesModule.getId());
            queryWrapper.eq(ChargeRulesModule::getChargeRulesId, chargeRulesModule.getChargeRulesId());
            queryWrapper.eq(ChargeRulesModule::getStartTimeHour, chargeRulesModule.getStartTimeHour());
            queryWrapper.eq(ChargeRulesModule::getStartTimeMinute, chargeRulesModule.getStartTimeMinute());
            if (CollectionUtil.isNotEmpty(this.list(queryWrapper))) {
                throw new Exception("重复配置");
            }
            ChargeRulesModule primaryChargeRuleModule = this.getPrimaryChargeRuleModule(chargeRulesModule);

            ChargeRulesModule nextChargeRuleModule = this.getNextChargeRuleModule(chargeRulesModule);
            if (nextChargeRuleModule == null||(nextChargeRuleModule.getId().equals(primaryChargeRuleModule.getId())&&chargeRulesModule.getId().equals(primaryChargeRuleModule.getId()))) {
                chargeRulesModule.setEndTimeHour(chargeRulesModule.getStartTimeHour());
                chargeRulesModule.setEndTimeMinute(chargeRulesModule.getStartTimeMinute());
            } else {
                primaryChargeRuleModule.setEndTimeHour(chargeRulesModule.getStartTimeHour());
                primaryChargeRuleModule.setEndTimeMinute(chargeRulesModule.getStartTimeMinute());
                chargeRulesModule.setEndTimeHour(nextChargeRuleModule.getStartTimeHour());
                chargeRulesModule.setEndTimeMinute(nextChargeRuleModule.getStartTimeMinute());
                if (JddConstant.ChargeConstant.CHARGE_RULE_MODULE_CHARGE_TYPE_STEP.equals(primaryChargeRuleModule.getChargeType())) {
                    result = "此计费时段的前置时段被修改，请及时调整";
                }
                this.updateById(primaryChargeRuleModule);
            }
            if (JddConstant.ChargeConstant.CHARGE_RULE_MODULE_CHARGE_TYPE_STEP.equals(chargeRulesModule.getChargeType())) {
                List<ChargeRulesModuleStep> addArray = new ArrayList<>();
                List<ChargeRulesModuleStep> stepArray = chargeRulesModuleVO.getStepArray();
                for (ChargeRulesModuleStep chargeRulesModuleStep : stepArray) {
                    chargeRulesModuleStep.setId(SnowFlakeUtil.getId());
                    chargeRulesModuleStep.setChargeRulesModuleId(chargeRulesModule.getId());
                    addArray.add(chargeRulesModuleStep);
                }
                chargeRulesModuleStepService.deleteByChargeRulesModuleId(chargeRulesModule.getId());
                if (CollUtil.isNotEmpty(addArray)) {
                    chargeRulesModuleStepService.saveBatch(addArray);
                }
            }
            this.updateById(chargeRulesModule);
            return "修改成功!" + result;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String delete(String chargeRulesModuleId) {
        String result = "";

        ChargeRulesModule chargeRulesModule = this.getById(chargeRulesModuleId);
        ChargeRulesModule primaryChargeRulesModule = this.getPrimaryChargeRuleModule(chargeRulesModule);
        ChargeRulesModule nextChargeRulesModule = this.getNextChargeRuleModule(chargeRulesModule);
        // 不止存在一种计费规则
        if (chargeRulesModule != primaryChargeRulesModule) {
            primaryChargeRulesModule.setEndTimeHour(nextChargeRulesModule.getStartTimeHour());
            primaryChargeRulesModule.setEndTimeMinute(nextChargeRulesModule.getStartTimeMinute());
            if (JddConstant.ChargeConstant.CHARGE_RULE_MODULE_CHARGE_TYPE_STEP.equals(primaryChargeRulesModule.getChargeType())) {
                result = "此计费时段的前置时段被修改，请及时调整!";
            }
            this.updateById(primaryChargeRulesModule);
        }
        this.removeById(chargeRulesModuleId);
        if (JddConstant.ChargeConstant.CHARGE_RULE_MODULE_CHARGE_TYPE_STEP.equals(chargeRulesModule.getChargeType())) {
            chargeRulesModuleStepService.deleteByChargeRulesModuleId(chargeRulesModule.getId());
        }
        return "删除成功!" + result;
    }

}
